﻿package com.firewolf.junit;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
 * 公用Util,用来调用一个类的方法，可以用来测试私有方法
 * @author Administrator
 *
 */
public class CallMethodUtil {
	/**
	 * 调用含单个参数的方法
	 * @param instance
	 * @param methodName
	 * @param arg
	 * @return
	 * @throws NoSuchMethodException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 */
	public static Object invokeMethod(Object instance, String methodName,
			Object arg) throws NoSuchMethodException, IllegalAccessException,
			InvocationTargetException {
		Object[] args = new Object[1];
		args[0] = arg;
		return invokeMethod(instance, methodName, args);
	}
	
	/**
	 * 调用包含多个参数的方法
	 * @param instance
	 * @param methodName
	 * @param args
	 * @return
	 * @throws NoSuchMethodException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 */
	public static Object invokeMethod(Object instance, String methodName,
			Object[] args) throws NoSuchMethodException,
			IllegalAccessException, InvocationTargetException {
		Class<?>[] classTypes = null;
		if (args != null) {
			classTypes = new Class[args.length];
			for (int i = 0; i < args.length; i++) {
				if (args[i] != null) {
					classTypes[i] = args[i].getClass();
				}
			}
		}
		return getMethod(instance, methodName, classTypes).invoke(instance,
				args);
	}
	/**
	 * 获取私有方法
	 * @param instance
	 * @param methodName
	 * @param classTypes
	 * @return
	 * @throws NoSuchMethodException
	 */
	private static Method getMethod(Object instance, String methodName,
			Class<?>[] classTypes) throws NoSuchMethodException {
		Method accessMethod = getMethod(instance.getClass(), methodName,
				classTypes);
		// 参数值为true，禁用访问控制检查
		accessMethod.setAccessible(true);
		return accessMethod;
	}

	/**
	 * 加载私有方法
	 * @param thisClass
	 * @param methodName
	 * @param classTypes
	 * @return
	 * @throws NoSuchMethodException
	 */
	private static Method getMethod(Class<?> thisClass, String methodName,
			Class<?>[] classTypes) throws NoSuchMethodException {
		if (thisClass == null) {
			throw new NoSuchMethodException("Error method !");
		}
		try {
			return thisClass.getDeclaredMethod(methodName, classTypes);
		} catch (NoSuchMethodException e) {
			return getMethod(thisClass.getSuperclass(), methodName, classTypes);
		}
	}
}
